package com.shenghua.utils;

import com.alibaba.fastjson.JSON;
import com.shenghua.utils.beans.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * Created by Administrator on 2019/5/22.
 */
@Component
public class RedisUtils {
    public static Logger logger = LoggerFactory.getLogger(RedisUtils.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void set(String key, String value) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列号value的实例化对象
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<String, Object> vo = redisTemplate.opsForValue();
        vo.set(key, value);
    }

    public void set(String key, String value, long seconds) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列号value的实例化对象
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<String, Object> vo = redisTemplate.opsForValue();
        vo.set(key, value, seconds);
    }

    public void setObject(String key, Object value) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列号value的实例化对象
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<String, Object> vo = redisTemplate.opsForValue();
        vo.set(key, JSON.toJSONString(value));
    }

    public void setObject(String key, Object value, long seconds) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列号value的实例化对象
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<String, Object> vo = redisTemplate.opsForValue();
        vo.set(key, JSON.toJSONString(value), seconds);
    }

    /**
     * 判断key是否存在
     * @param key 键值
     * @return boolean
     */
    public boolean exist(String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列号value的实例化对象
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<String, Object> vo = redisTemplate.opsForValue();
        Object value = vo.get(key);
        return StringUtils.isNotBlank(value);
    }

    /**
     * 删除key
     * @param key
     */
    public void delete(String key) {
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 持有锁
     * @param key
     * @return
     */
    public boolean lock(String key) {
        return redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException,NullPointerException {
                StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
                byte[] keyByte = stringRedisSerializer.serialize(key);
                byte[] valueByte = stringRedisSerializer.serialize("lock");
                boolean flag = redisConnection.setNX(keyByte, valueByte);
                // 防止死锁异常，设置最大处理的超时时间
                if(flag) redisConnection.expire(keyByte, Constants.RedisConstants.DEFAULT_EXPIRE);
                return flag;
            }
        });
    }

    public boolean lock(String key, String value) {
        return redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
                StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
                byte[] keyByte = stringRedisSerializer.serialize(key);
                byte[] valueByte = stringRedisSerializer.serialize(value);
                boolean flag = redisConnection.setNX(keyByte, valueByte);
                // 防止死锁异常，设置最大处理的超时时间
                if(flag) redisConnection.expire(keyByte, Constants.RedisConstants.DEFAULT_EXPIRE);
                return flag;
            }
        });
    }

    public boolean lock(String key, String value, long seconds) {
        return redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
                StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
                byte[] keyByte = stringRedisSerializer.serialize(key);
                byte[] valueByte = stringRedisSerializer.serialize(value);
                boolean flag = redisConnection.setNX(keyByte, valueByte);
                // 防止死锁异常，设置最大处理的超时时间
                if(flag) redisConnection.expire(keyByte, seconds);
                return flag;
            }
        });
    }

    /**
     * 释放锁
     * @param key
     */
    public void unlock(String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());//加锁时序列化，释放锁也要序列化
        redisTemplate.delete(key);
    }
}
